<?php


namespace Payment\Common\TLpay;

use Payment\Common\BaseData;
use Payment\Common\BaseStrategy;
use Payment\Common\PayException;
use Payment\Common\TLConfig;
use Payment\Utils\ArrayUtil;
use Payment\Utils\Curl;

/**
 * Created by IntelliJ IDEA.
 * User: yeran
 * Date: 2018/4/21
 * Time: 下午11:39
 */

abstract class TLBaseStrategy implements BaseStrategy{

    /**
     * 通联支付的配置文件
     * @var TLConfig $config
     */
    protected $config;

    /**
     * 支付数据
     * @var BaseData $reqData
     */
    protected $reqData;

    /**
     * WxBaseStrategy constructor.
     * @param array $config
     * @throws PayException
     */
    public function __construct(array $config)
    {
        /* 设置内部字符编码为 UTF-8 */
        mb_internal_encoding("UTF-8");

        try {
            $this->config = new TLConfig($config);
        } catch (PayException $e) {
            throw $e;
        }
    }

    /**
     * 发送完了请求
     * @param  array $body
     * @return mixed
     * @throws PayException
     * 
     */
    protected function sendReq($body)
    {
        $url = $this->getReqUrl();
        if (is_null($url)) {
            throw new PayException('目前不支持该接口。请联系开发者添加');
        }

        $responseTxt = $this->curlPost($body, $url);

        // 格式化为数组
        $retData = json_decode($responseTxt,true);

      //  var_dump($retData);

        if ($retData['retcode'] != 'SUCCESS') { //通信标识
            throw new PayException('支付平台返回错误提示1:' . $retData['retmsg']);
        }
        if ($retData['trxstatus'] != '0000') {//交易标识
            $msg = $retData['errmsg']?:'交易失败-系统繁忙';
            throw new PayException('支付平台返回错误提示2:' . $msg);
        }

        return $retData;
    }

    /**
     * 父类仅提供基础的post请求，子类可根据需要进行重写
     * @param array $body
     * @param string $url
     * @return mixed
     * 
     */
    protected function curlPost($body, $url)
    {
        $curl = new Curl();
        $paramsStr = ArrayUtil::ToUrlParams($body);

        return $curl->request($url, $paramsStr);
    }

    /**
     * 获取需要的url  默认返回下单的url
     * 
     * @return string|null
     */
    protected function getReqUrl()
    {
        return TLConfig::UNIFIED_URL;
    }

    /**
     * @param array $data
     * 
     * @throws PayException
     * @return array|string
     */
    public function handle(array $data)
    {
        $buildClass = $this->getBuildDataClass();

        try {
            $this->reqData = new $buildClass($this->config, $data);
        } catch (PayException $e) {
            throw $e;
        }

        $this->reqData->setSign();//计算sign，整理数据格式

        $body = $this->reqData->getData();
        $ret = $this->sendReq($body);

        // 检查返回的数据是否被篡改
        $flag = $this->verifySign($ret);
        if (!$flag) {
            throw new PayException('支付平台返回数据被篡改。请检查网络是否安全！');
        }

        return $this->retData($ret);
    }

    /**
     * 处理支付平台的返回值并返回给客户端
     * @param array $ret
     * @return mixed
     * 
     */
    protected function retData(array $ret)
    {
        return $ret;
    }

    /**
     * 检查支付平台返回的数据是否被篡改过:sign=md5(string.getbyte("utf-8")).toUpperCase()
     * @param array $retData
     * @return boolean
     * 
     */
    protected function verifySign(array $retData)
    {
        $retSign = $retData['sign'];
        $values = ArrayUtil::removeKeys($retData, ['sign', 'sign_type']);

        $values = ArrayUtil::paraFilter($values);

        $signStr = ArrayUtil::SignArray($values,$this->config->md5Key);

        return strtoupper($signStr) === $retSign;
    }

}